home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2010 Summer - Disc 1 / WN_Ete2010_CD1.iso / Onglet5 / Weezo / Weezo setup.exe / {code_appDir} / www / includes / proxyFunctions.php < prev    next >
PHP Script  |  2010-05-19  |  52KB  |  1,321 lines

  1. <?php
  2. /**
  3.  * Proxy functions
  4.  *
  5.  * PHP version 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   NA
  14.  * @package    NA
  15.  * @author     Nicolas Bruley / Peer 2 World <contact@weezo.net>
  16.  * @copyright  2005-2009 Nicolas Bruley / Peer 2 World
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    CVS: $Id:$
  19.  * @link       http://www.weezo.net
  20.  * @since      File available since Release 1.0.9
  21.  */
  22.  
  23. $processedLinkAttributes=array('href', 'src', 'action');
  24. $processedJSAttributes=array('onclick', 'onmouseover', 'onmouseout', 'ondblclick', 'onload', 'onresize', 'onabort', 'onblur', 'onchange', 'onerror', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup','onmousedown', 'onmouseup', 'onmousemove', 'onreset', 'onselect', 'onsubmit', 'onunload');
  25.  
  26. /**
  27.  * @desc Set proxy options from resource session data
  28.  *
  29.  */
  30. function proxySetOptions(){
  31.     if(!isset($_ENV['options']['noReferer'])) {
  32.         $_ENV['options']['noReferer']=false;
  33.         if(cfRGetVar('optionNoReferer')) $_ENV['options']['noReferer']=true;
  34.     }
  35.     if(!isset($_ENV['options']['noPopups'])) {
  36.         $_ENV['options']['noPopups']=false;
  37.         if(cfRGetVar('optionNoPopups')) $_ENV['options']['noPopups']=true;
  38.     }
  39.     if(!isset($_ENV['options']['noScripts'])) {
  40.         $_ENV['options']['noScripts']=false;
  41.         if(cfRGetVar('optionNoScripts')) $_ENV['options']['noScripts']=true;
  42.     }
  43.     if(!isset($_ENV['options']['noCookies'])) {
  44.         $_ENV['options']['noCookies']=false;
  45.         if(cfRGetVar('optionNoCookies')) $_ENV['options']['noCookies']=true;
  46.     }
  47.  
  48. }
  49.  
  50. /**
  51.  * Decode gzip compressed page
  52.  *
  53.  * @param string $data : compressed data
  54.  * @return string : uncompressed data
  55.  */
  56. function gzdecode ($data) {
  57.     $flags = ord(substr($data, 3, 1));
  58.     $headerlen = 10;
  59.     $extralen = 0;
  60.     $filenamelen = 0;
  61.     if ($flags & 4) {
  62.         $extralen = unpack('v' ,substr($data, 10, 2));
  63.         $extralen = $extralen[1];
  64.         $headerlen += 2 + $extralen;
  65.     }
  66.     if ($flags & 8) // Filename
  67.         $headerlen = strpos($data, chr(0), $headerlen) + 1;
  68.     if ($flags & 16) // Comment
  69.         $headerlen = strpos($data, chr(0), $headerlen) + 1;
  70.     if ($flags & 2) // CRC at end of file
  71.         $headerlen += 2;
  72.     $unpacked = gzinflate(substr($data, $headerlen));
  73.     if ($unpacked === FALSE)
  74.           $unpacked = $data;
  75.     return $unpacked;
  76.  }
  77.  
  78. /**
  79.  * @desc Send headers received from website to browser
  80.  *
  81.  * @param string $fullStatus: HTTP response status (HTTP/1.x: XXX xxxxx)
  82.  * @param array $headers: array of headers
  83.  * @param boolean $justDisplay : set to true to display headers instead of sending them
  84.  */
  85. function proxySendHeadersToBrowser($fullStatus, $headers,$justDisplay=false){
  86.     // Process headers
  87.     if(isset($headers['location'])) $headers['location']=proxyEncodeUrlPHP(proxyURLSetAbsolute($headers['location']));
  88.     if(isset($headers['content-location'])) $headers['content-location']=proxyEncodeUrlPHP(proxyURLSetAbsolute($headers['content-location']));
  89.     if(isset($headers['refresh'])&&strpos($headers['refresh'],'URL='))
  90.         $headers['refresh']=substr($headers['refresh'],0,strpos($headers['refresh'],'URL=')+4).proxyEncodeUrlPHP(proxyURLSetAbsolute(substr($headers['refresh'],strpos($headers['refresh'],'URL=')+4)));
  91.  
  92.     // Remove cookies
  93.     unset($headers['set-cookie']);
  94.     unset($headers['warning']);
  95.     unset($headers['content-md5']);
  96.  
  97.     if(!$justDisplay) {
  98.         // HTTP response header
  99.         header($fullStatus);
  100.         // Other headers
  101.         foreach ($headers as $key=>$value) header(ucfirst($key).': '.$value);
  102.     }
  103.     else {
  104.         echo '<div style="background:#FEE;border:1px solid #DDD;padding:5px;margin-bottom:1em">';
  105.         echo $decodedURL.'<br>';
  106.         echo $fullStatus.'<br>';
  107.         foreach ($headers as $key=>$value) echo (ucfirst($key).': '.$value)."<br>\n";
  108.         echo '</div>';
  109.     }
  110. }
  111.  
  112. /**
  113.  * Turns a relative or absolute URL into absolute URL, from $_ENV['siteURLHost'].$_ENV['siteURLPath'] URL
  114.  *
  115.  * @param string $url
  116.  * @return string: absolute URL
  117.  */
  118. function proxyURLSetAbsolute($url){
  119.  
  120.     if(!$url) return $_ENV['siteURLHost'].$_ENV['siteURLPath'];
  121.     if(substr($url,0,2)=='//') $url=$_ENV['siteURLScheme'].':'.$url;
  122.     if(substr(strtolower($url),0,7)!='http://' && substr(strtolower($url),0,8)!='https://'){
  123.         if($url[0]!='/') {
  124.             // If HTML doc has a <base> node, use its href attribute as base path
  125.             if(isset($_ENV['baseHref']) && $_ENV['baseHref']) $url=$_ENV['baseHref'].$url;
  126.             else $url=$_ENV['siteURLPath'].'/'.$url;
  127.         }
  128.         $count=1;
  129.         // Replace /youpi/../ by /
  130.         while($count) $url=preg_replace("/\/[^\/]+\/[.]{2}/","",$url,-1,$count);
  131.         // Remove remaining /../ (but there should be none)
  132.         $url=str_replace('/../','/',$url);
  133.         // Add site host if needed
  134.         if(substr(strtolower($url),0,4)!='http') $url=$_ENV['siteURLHost'].$url;
  135.     }
  136.     return $url;
  137. }
  138.  
  139. /**
  140.  * @desc Encode an URL
  141.  *
  142.  * @param string $url: absolute URL to encode
  143.  * @return string: encoded URL
  144.  */
  145. function proxyEncodeUrlPHP($url,$tagName=false){
  146.     if(substr(strtolower($url),0,7)!='http://' && substr(strtolower($url),0,8)!='https://') $url='http://'.$url;
  147.     //$enc=str_replace('/','_',str_replace('=','-',base64_encode((strpos($url,'?'))?substr($url,0,strpos($url,'?')):$url)));
  148.     $enc=str_replace('/','_',str_replace('=','-',base64_encode($url)));
  149.     if(strtolower($tagName=='script')) $mimeType='js/';
  150.     elseif(strtolower($tagName=='style')) $mimeType='css/';
  151.     else $mimeType='';
  152.     return $_ENV['baseURLProxy'].chunk_split($enc,254,'/').'/eourl/'.$mimeType.'a'.basename(((strpos($url,'?'))?substr($url,0,strpos($url,'?')):$url));
  153. }
  154.  
  155. /**
  156.  * @desc Decode encoded URL from SERVER URI
  157.  *
  158.  * @param string $url: URL to decode
  159.  * @return string: decoded URL
  160.  */
  161. function proxyDecodeUrlPHP($url=false){
  162.     if($url) $url=substr($url,strpos($url,'/',9));
  163.     $encoded=substr((($url)?$url:$_SERVER['REQUEST_URI']),strlen(dirname($_SERVER['PHP_SELF']))+1);
  164.     if(strpos($encoded,'?')) $get=substr($encoded,strpos($encoded,'?')); else $get='';
  165.     if($get=='?') $get='';
  166.     $encoded=substr($encoded,0,strpos($encoded,'/eourl/'));
  167.     $encoded=str_replace('/','',$encoded);
  168.     //cfDbg('Decoded:'.base64_decode(str_replace('_','/',str_replace('-','=',$encoded))).$get.' --- enc:'.$encoded,1);
  169.  
  170.     // If no new GET parameter passed, use original encoded URL
  171.     if(!$get) return base64_decode(str_replace('_','/',str_replace('-','=',$encoded)));
  172.  
  173.     // If a GET parameter is passed, remove get parameter b64 encoded in original url
  174.     $b64Clear=base64_decode(str_replace('_','/',str_replace('-','=',$encoded)));
  175.     if(strpos($b64Clear,'?')) $b64Clear=substr($b64Clear,0,strpos($b64Clear,'?'));
  176.     return $b64Clear.$get;
  177. }
  178.  
  179.  
  180. /**
  181.  * @desc Process href, src, onclick, onmouse... attributes
  182.  *
  183.  * @param string $attrValue: attribute value
  184.  * @return string: processed attribute
  185.  */
  186. function processHRef($attrValue, $tagName=false){
  187.     $attrValue=trim($attrValue);
  188.     if($attrValue=='#') return '#';
  189.     // Javascript
  190.     if(strtolower(substr($attrValue,0,11)=='javascript:')) return 'javascript:'.proxyProcessJavascript(substr($attrValue,11));
  191.  
  192.     // inline data ("data:")
  193.     if(strtolower(substr($attrValue,0,5)=='data:')) {
  194.         $data=trim(substr($attrValue,5));
  195.  
  196.         // not javascript: don't touch
  197.         if(substr($data,0,15)!='text/javascript') return $attrValue;
  198.  
  199.         // inline javascript code
  200.         $data=rawurldecode(substr($data,16));
  201.         if(substr($data,0,7)=='base64,') $data=base64_decode(substr($data,7));
  202.  
  203.         // protect javascript code
  204.         return 'data:text/javascript;base64,'.rawurlencode(base64_encode(proxyProcessJavascript($data)));
  205.     }
  206.  
  207.     // Link
  208.     return proxyEncodeUrlPHP(proxyURLSetAbsolute($attrValue),$tagName);
  209. }
  210. /**
  211.  * @desc Process a node's attributes
  212.  *
  213.  * @param HTML node: $node
  214.  */
  215. function proxyProcessNode(&$node){
  216.     global $processedLinkAttributes;
  217.     global $processedJSAttributes;
  218.  
  219.     $nodeName=$node->nodeName;
  220.  
  221.     // 'href', 'src', 'action'
  222.     foreach ($processedLinkAttributes as $attr){
  223.         if(strtolower($nodeName)=='link' && $node->hasAttribute('rel') && $node->getAttribute('rel')=='stylesheet') $nodeName='style';
  224.         if($node->hasAttribute($attr)) $node->setAttribute($attr,processHRef($node->getAttribute($attr),$nodeName));
  225.     }
  226.     // 'onclick', 'onmouseover', 'onmouseout' ...
  227.     foreach ($processedJSAttributes as $attr)
  228.         if($node->hasAttribute($attr)) $node->setAttribute($attr,proxyProcessJavascript($node->getAttribute($attr)));
  229.     if($node->hasAttribute('style')) $node->setAttribute('style',proxyProcessCSS($node->getAttribute('style')));
  230.  
  231.     foreach ($node->childNodes as $cn) if($cn->nodeType==XML_ELEMENT_NODE) proxyProcessNode($cn);
  232. }
  233.  
  234.  
  235. function proxyProtectJavascriptCB($matches){
  236.     //cfDbg($matches[3],1);
  237.     //if(!$matches[3]) $matches[4]=$matches[3].'=>'.$matches[1].(($matches[3])?'b64'.base64_encode($matches[3]):'').'</script';
  238.     //if(!$matches[3]) cfDbg($matches,1);
  239.     //cfDbg($matches[3].'=>'.$matches[1].(($matches[3])?'b64'.base64_encode($matches[3]):'').'</script',1);
  240.     return $matches[1].(($matches[3])?'b64'.base64_encode($matches[3]):'').'</script';
  241. }
  242. function proxyUnprotectJavascriptCB($matches){
  243.     //cfDbg(base64_decode($matches[1]),1);
  244.     return '>'.base64_decode($matches[1]).'<';
  245. }
  246.  
  247. /**
  248.  * @desc url() replacement preg_match_callback function
  249.  */
  250. // ActiveXObject("Microsoft.XMLHTTP") and XMLHttpRequest() open method replacement
  251. function proxyProcessJavascriptCB1($matches){
  252.     return '.open('.$matches[1].',proxyEncodeURL('.$matches[2].')'.((isset($matches[3]))?$matches[3]:'').')';
  253. }
  254.  
  255. // Replaces "siteHref.href ="
  256. function proxyProcessJavascriptCB2($matches){return 'proxyDocumentLocationNode.value='.$matches[1];}
  257.  
  258. // Replaces (document.)location by siteHref, and document.cookie by proxyGetCookie
  259. function proxyProcessJavascriptCB3($matches){
  260.     if(isset($matches[4])) $matches[4]=trim($matches[4]);
  261.     // If quoted, don't transform
  262.     if(trim($matches[2])=='.' || $matches[4]=='"' || $matches[4]=='"') return $matches[0];
  263.     if($matches[0][0]=='"' || $matches[0][1]=="'") return $matches[0];
  264.     if(trim($matches[3])=='location'){
  265.         if(strpos($matches[0],'document')!==false) return substr($matches[0],0,strpos($matches[0],'document')).'siteHref'.$matches[4];
  266.         elseif(strpos($matches[0],'self')!==false) return substr($matches[0],0,strpos($matches[0],'self')).'siteHref'.$matches[4];
  267.         return $matches[2].'siteHref'.$matches[4];
  268.     }
  269.     elseif(trim($matches[3])=='cookie' && strpos($matches[0],'document')!==false){
  270.         return substr($matches[0],0,strpos($matches[0],'document')).'proxyGetCookie()'.$matches[4];
  271.     }
  272.     return $matches[0];
  273. }
  274. // (document.)location "set" replacement
  275. function proxyProcessJavascriptCB4($matches){
  276.     if(substr($matches[2],0,8)=='document'||substr($matches[2],0,4)=='self') return 'proxyDocumentLocationNode.value=';
  277.     if(substr(trim($matches[2]),-1)=='.') return $matches[0];
  278.     return $matches[2].'proxyDocumentLocationNode.value=';
  279. }
  280. // setTimeout, setInterval & eval replacement
  281. function proxyProcessJavascriptCB5($matches){
  282.     return 'proxy'.ucfirst($matches[0]);
  283.     return '.'.$matches[1].'=proxyEncodeURL('.$matches[2].')';
  284. }
  285.  
  286. // x = document; replacement
  287. function proxyProtectJavascriptCB6($matches){return '=proxyDoc'.$matches[1];}
  288.  
  289. /**
  290.  * @desc Process javascript text
  291.  *
  292.  * @param string $script
  293.  * @return string
  294.  */
  295. function proxyProcessJavascript($script){
  296.     /* $inquote value :
  297.     0 : out of quotes
  298.     1 : single quote '
  299.     2 : double quote "
  300.     3 : simple comment //
  301.     4 : passge comment * /
  302.     */
  303.  
  304.     // Remove javascript option
  305.     if(isset($_ENV['options']['noScripts']) && $_ENV['options']['noScripts']) return '';
  306.  
  307.     // ActiveXObject("Microsoft.XMLHTTP") and XMLHttpRequest() open method replacement
  308.     $script=preg_replace_callback("/\.\s*open\s*\(\s*(\"post\"|\"get\")\s*,([^)\,]*)(,([^)]*)){0,1}\)/i", "proxyProcessJavascriptCB1", $script);
  309.  
  310.     // top and parent replacement
  311.     $script=str_replace('top.','',str_replace('parent.','',$script));
  312.  
  313.     // Remove cookie actions if set in options
  314.     if($_ENV['options']['noCookies'])
  315.         $script=preg_replace('/(document\s*\.){1,1}cookie\s*=/','proxyFoo=',$script);
  316.  
  317.     // window.open(x) => window.open(proxyEncodeURL(x))
  318.     $pattern="/window\s*\.\s*open\s*\(/";
  319.     $new='';
  320.     while(preg_match($pattern, $script, $matches, PREG_OFFSET_CAPTURE)){
  321.         $stack='';    $lastStack='';    $inquote=false;
  322.         $sp=$matches[0][1]+strlen($matches[0][0]);
  323.         $new.=substr($script,0,$sp);
  324.         $script=substr($script,$sp);
  325.         $sp=0; $prevc='';
  326.         if($script[0]=='=') continue;
  327.         $strlen=strlen($script);
  328.         while($sp<$strlen){
  329.             $c=$script[$sp];
  330.             if(!$inquote){
  331.                 if(!$stack && ($c==')' || $c==',')) break;
  332.                 else{
  333.                     if(($c==')'&&$lastStack=='(')||($c=='}'&&$lastStack=='{')||($c==']'&&$lastStack=='['))
  334.                         {$stack=substr($stack,0,strlen($stack)-1); $lastStack=substr($stack,-1);}
  335.                     elseif($c=='('||$c=='{'||$c=='['){$lastStack=$c;$stack.=$c;}
  336.                     elseif($c=="'") $inquote=1;
  337.                     elseif($c=='"') $inquote=2;
  338.                     elseif($c=='/' && $prevc=='/') $inquote=3;
  339.                     elseif($c=='*' && $prevc=='/') $inquote=4;
  340.                 }
  341.             }
  342.             else{
  343.                 if((($inquote==1&&$c=="'")||($inquote==2&&$c=='"'))&&$prevc!='\\') $inquote=0;
  344.                 elseif($inquote==3 && (($c=="\n" || $c=="\r") || ($c=="/" && $prevc=='/'))) $inquote=0;
  345.                 elseif($inquote==4 && $c=="/" && $prevc=='*') $inquote=0;
  346.             }
  347.             $prevc=$c;
  348.             $sp++;
  349.         }
  350.         if($sp) $new.='proxyEncodeURL('.substr($script,0,$sp).')';
  351.         $script=substr($script,$sp);
  352.     }
  353.  
  354.     $script=$new.$script;
  355.  
  356.     // action, src, innerHTML, location, URL and href += method replacement
  357.     $pattern="/(\.\s*src|\.\s*action|\.\s*href|\.\s*URL|\.\s*innerHTML|\s*location)\s*(\+)\s*=/";
  358.     $del=";{}\n\r+-=*!:?|&/><](";
  359.     $pos=0;
  360.     $prevc='';
  361.     while(preg_match($pattern, $script, $matches, PREG_OFFSET_CAPTURE,$pos)){
  362.         $sp=$matches[0][1];
  363.         $complete=false;
  364.         $stack='';    $lastStack='';    $inquote=false;
  365.         while($sp>=0){
  366.             $c=$script[$sp];
  367.             if(!$inquote){
  368.                 // Try to guess if carriage return is an end of line
  369.                 if(!$stack && $c=="\n"||$c=="\r"){
  370.                     $lc=substr(trim(substr($script,0,$sp)),-1);
  371.                     $del2="\r\n     ";
  372.                     $sp2=$sp+1;$lsc=strlen($script);while($sp2<$lsc && strpos($del2,$script[$sp2])!==false) $sp2++;
  373.                     // End of script => end of instruction
  374.                     if($sp2==$lsc) break;
  375.                     $del2="+-&|!.(";
  376.                     // Instruction finished
  377.                     if(strpos($del2,$lc)===false && strpos($del2,$script[$sp2])===false) break;
  378.                 }
  379.  
  380.                 if(!$stack && strpos($del,$c)!==false) break;
  381.                 else{
  382.                     if(($c=='('&&$lastStack==')')||($c=='['&&$lastStack==']'))
  383.                         {$stack=substr($stack,0,strlen($stack)-1); $lastStack=substr($stack,-1);}
  384.                     elseif($c==')'||$c==']'){
  385.                         if($prevc!='.') break;
  386.                         $lastStack=$c;$stack.=$c;
  387.                     }
  388.                     elseif($c=="'") $inquote=1;
  389.                     elseif($c=='"') $inquote=2;
  390.                 }
  391.             }
  392.             else{
  393.                 if((($inquote==1&&$c=="'")||($inquote==2&&$c=='"'))) $inquote=0;
  394.             }
  395.             if($c!=' ' && $c!=chr(11)) $prevc=$c;
  396.             $sp--;
  397.         }
  398.         $found=substr($script,$sp+1,$matches[1][1]+strlen($matches[1][0])-$sp-1);
  399.         $pos=$matches[2][1]; $script[$pos]=' ';
  400.         $script=substr($script,0,$matches[0][1]+strlen($matches[0][0])).$found.'+'.substr($script,$matches[0][1]+strlen($matches[0][0]));
  401.     }
  402.  
  403.     // domain/URL replacement
  404.     $del=";{}\n\r+-=*!:?|&/><,](";
  405.     $pos=0;
  406.     $prevc='';
  407.     while(($sp=strpos($script,'.domain',$pos)) || ($sp=strpos($script,'. domain',$pos)) || ($sp=strpos($script,'.URL',$pos)) || ($sp=strpos($script,'. URL',$pos))){
  408.         $complete=false;
  409.         $stack='';    $lastStack='';    $inquote=false;
  410.         if(substr($script,$sp,3)=='. d') $domainL=8;
  411.         elseif(substr($script,$sp,2)=='.d') $domainL=7;
  412.         elseif(substr($script,$sp,2)=='.U') $domainL=4;
  413.         else $domainL=5;
  414.         $pos=$sp+$domainL;
  415.  
  416.         // Verify that it's actually "domain" or "URL"
  417.         if(strlen($script)==$pos-1 || preg_match("/[\w]/",$script[$pos]) || $script[$pos]=='.')    continue;
  418.  
  419.         // reverse browse $script for start of variable
  420.         while($sp>=0){
  421.             $c=$script[$sp];
  422.             if(!$inquote){
  423.                 // Try to guess if carriage return is an end of line
  424.                 if(!$stack && $c=="\n"||$c=="\r"){
  425.                     $lc=substr(trim(substr($script,0,$sp)),-1);
  426.                     $del2="\r\n     ";
  427.                     $sp2=$sp+1;$lsc=strlen($script);while($sp2<$lsc && strpos($del2,$script[$sp2])!==false) $sp2++;
  428.                     // End of script => end of instruction
  429.                     if($sp2==$lsc) break;
  430.                     $del2="+-&|!.(";
  431.                     // Instruction finished
  432.                     if(strpos($del2,$lc)===false && strpos($del2,$script[$sp2])===false) break;
  433.                 }
  434.  
  435.                 if(!$stack && strpos($del,$c)!==false) break;
  436.                 else{
  437.                     if(($c=='('&&$lastStack==')')||($c=='['&&$lastStack==']'))
  438.                         {$stack=substr($stack,0,strlen($stack)-1); $lastStack=substr($stack,-1);}
  439.                     elseif($c==')'||$c==']'){
  440.                         if($prevc!='.') break;
  441.                         $lastStack=$c;$stack.=$c;
  442.                     }
  443.                     elseif($c=="'") $inquote=1;
  444.                     elseif($c=='"') $inquote=2;
  445.                 }
  446.             }
  447.             else{
  448.                 if((($inquote==1&&$c=="'")||($inquote==2&&$c=='"'))) $inquote=0;
  449.             }
  450.             if($c!=' ' && $c!=chr(11)) $prevc=$c;
  451.             $sp--;
  452.         }
  453.         if(substr($script,$sp,3)=='. d' || substr($script,$sp,2)=='.d')
  454.             $script=substr($script,0,$sp+1).'siteHref.domain'.substr($script,$pos);
  455.         else
  456.             $script=substr($script,0,$sp+1).'siteHref.href'.substr($script,$pos);
  457.         $pos=$sp+11;
  458.     }
  459.  
  460.  
  461.  
  462.  
  463.     // action, src, innerHTML and href method replacement
  464.     // include document.cookie replacement too
  465.     $pattern="/(\.\s*src|\.\s*action|\.\s*href|\.\s*innerHTML|[^.]\s*document\s*\.\s*cookie)\s*=/";
  466.     $new='';
  467.     while(preg_match($pattern, $script, $matches, PREG_OFFSET_CAPTURE)){
  468.         // Remove 1st non-matching chars of document.cookie
  469.         if(strpos($matches[0][0],'document')){
  470.             $offset=strpos($matches[0][0],'doc');
  471.             $matches[0][0]=substr($matches[0][0],strpos($matches[0][0],'doc'));$matches[0][1]+=$offset;
  472.             $matches[1][0]=substr($matches[1][0],strpos($matches[1][0],'doc'));$matches[1][1]+=$offset;
  473.         }
  474.         $stack='';    $lastStack='';    $inquote=false;
  475.         $sp=$matches[0][1]+strlen($matches[0][0]);
  476.         $new.=substr($script,0,$sp);
  477.         //if($matches[0][0]=='.src =') cfDbg($script);
  478.         //cfVarDump($matches,1);
  479.         $script=substr($script,$sp);
  480.         $sp=0; $prevc='';
  481.         if($script[0]=='=') continue; // Do not process "=="
  482.         $strlen=strlen($script);
  483.         while($sp<$strlen){
  484.             $c=$script[$sp];
  485.             if(!$inquote){
  486.                 // Try to guess if carriage return is an end of instruction
  487.                 if(!$stack && $c=="\n"||$c=="\r"){
  488.                     $lc=substr(trim(substr($script,0,$sp)),-1);
  489.                     $del="\r\n     ";
  490.                     $sp2=$sp+1;$lsc=strlen($script);while($sp2<$lsc && strpos($del,$script[$sp2])!==false) $sp2++;
  491.                     // End of script => end of instruction
  492.                     if($sp2==$lsc) break;
  493.                     $del="+-&|!.(";
  494.                     // Instruction finished
  495.                     if(strpos($del,$lc)===false && strpos($del,$script[$sp2])===false) break;
  496.                 }
  497.                 if(!$stack && ($c==';'||$c==')'||$c=='}'||$c==']')) break;
  498.                 else{
  499.                     if(($c==')'&&$lastStack=='(')||($c=='}'&&$lastStack=='{')||($c==']'&&$lastStack=='['))
  500.                         {$stack=substr($stack,0,strlen($stack)-1); $lastStack=substr($stack,-1);}
  501.                     elseif($c=='('||$c=='{'||$c=='['){$lastStack=$c;$stack.=$c;}
  502.                     elseif($c=="'") $inquote=1;
  503.                     elseif($c=='"') $inquote=2;
  504.                     elseif($c=='/' && $prevc=='/') $inquote=3;
  505.                     elseif($c=='*' && $prevc=='/') $inquote=4;
  506.                 }
  507.             }
  508.             else{
  509.                 if((($inquote==1&&$c=="'")||($inquote==2&&$c=='"'))&&$prevc!='\\') $inquote=0;
  510.                 elseif($inquote==3 && (($c=="\n" || $c=="\r") || ($c=="/" && $prevc=='/'))) $inquote=0;
  511.                 elseif($inquote==4 && $c=="/" && $prevc=='*') $inquote=0;
  512.             }
  513.             $prevc=$c;
  514.             $sp++;
  515.         }
  516.         // innerHTML : use proxyJSProcessHTML (HTML encoding) function
  517.         if($sp && stripos($matches[1][0],'innerhtml')) $new.='proxyJSProcessHTML('.substr($script,0,$sp).')';
  518.  
  519.         // Set cookie
  520.         elseif($sp && stripos($matches[1][0],'cookie'))
  521.             $new=substr($new,0,strlen($new)-strlen($matches[0][0])).'proxySetCookie('.substr($script,0,$sp).')';
  522.  
  523.         // src/action/href/location : use proxyEncodeURL (URL encoding) function
  524.         elseif($sp) $new.='proxyEncodeURL('.substr($script,0,$sp).')';
  525.  
  526.         $script=substr($script,$sp);
  527.     }
  528.  
  529.     $script=$new.$script;
  530.  
  531.     // Document.write replacement
  532.     $pattern="/(document\s*.\s*write(ln){0,1}\s*\()/";
  533.     $new='';
  534.     while(preg_match($pattern, $script, $matches, PREG_OFFSET_CAPTURE)){
  535.         $stack='';    $lastStack='';    $inquote=false;
  536.         $sp=$matches[0][1]+strlen($matches[0][0]);
  537.         $new.=substr($script,0,$matches[0][1]).((isset($matches[2]))?'proxyDocumentWriteln(':'proxyDocumentWrite(');
  538.         $script=substr($script,$sp);
  539.         $sp=0; $prevc='';$strlen=strlen($script);
  540.         while($sp<$strlen){
  541.             $c=$script[$sp];
  542.             if(!$inquote){
  543.                 if($c=="\n"||$c=='\r') $script[$sp]=' ';
  544.                 // End of instruction found
  545.                 if(!$stack && ($c==';'||$c=="\r"||$c==')'||$c=='}'||$c==']')) {
  546.                     // Check if instruction is followed by another document.write
  547.                     $sp2=$sp+1;
  548.                     while ($sp2<$strlen && ($script[$sp2]=="\n" || $script[$sp2]=="\r" || $script[$sp2]==';' || $script[$sp2]==' ' || $script[$sp2]=="\t")) $sp2++;
  549.                     // if so...
  550.                     if(substr($script,$sp2,8)=='document' && preg_match('/^document\s*\.\s*write(ln){0,1}\s*\(/',substr($script,$sp2),$matches)){
  551.                         // Join both document.write by spaces and a +
  552.                         while($sp<$sp2+strlen($matches[0])-1) $script[$sp++]=' ';
  553.                         $script[$sp]='+';
  554.                     }
  555.                     else break;
  556.                 }
  557.                 else{
  558.                     if(($c==')'&&$lastStack=='(')||($c=='}'&&$lastStack=='{')||($c==']'&&$lastStack=='['))
  559.                         {$stack=substr($stack,0,strlen($stack)-1); $lastStack=substr($stack,-1);}
  560.                     elseif($c=='('||$c=='{'||$c=='['){$lastStack=$c;$stack.=$c;}
  561.                     elseif($c=="'") $inquote=1;
  562.                     elseif($c=='"') $inquote=2;
  563.                     elseif($c=='/' && $prevc=='/') $inquote=3;
  564.                     elseif($c=='*' && $prevc=='/') $inquote=4;
  565.                 }
  566.             }
  567.             else{
  568.                 if((($inquote==1&&$c=="'")||($inquote==2&&$c=='"'))&&$prevc!='\\') $inquote=0;
  569.                 elseif($inquote==3 && (($c=="\n" || $c=="\r") || ($c=="/" && $prevc=='/'))) $inquote=0;
  570.                 elseif($inquote==4 && $c=="/" && $prevc=='*') $inquote=0;
  571.             }
  572.             $prevc=$c;
  573.             $sp++;
  574.         }
  575.  
  576.         if($sp) $new.=substr($script,0,$sp);
  577.         $script=substr($script,$sp);
  578.     }
  579.     $script=$new.$script;
  580.  
  581.     // (document/self.)location & cookie "get" replacement
  582.     $script=preg_replace_callback("/(([^.\sa-zA-Z]\s*document\s*\.\s*|[^.\sa-zA-Z]\s*self\s*\.\s*|\.\s*|\W)(location|cookie))(\s*[^=\s]|\s*[=]{2})/", 'proxyProcessJavascriptCB3', $script);
  583.  
  584.     // replaces "siteHref.href ="
  585.     $script=preg_replace_callback("/siteHref\.href\s*=([^=])/", 'proxyProcessJavascriptCB2', $script);
  586.  
  587.     // (document/self.)location "set" replacement
  588.     $script=preg_replace_callback("/((document\s*\.\s*|self\s*\.\s*|\W)location(\s*\.\s*href){0,1})(\s*=)/",'proxyProcessJavascriptCB4', $script);
  589.  
  590.     // setTimeout, setInterval & eval replacement
  591.     $script=preg_replace_callback("/(setTimeout|setInterval|eval)\s*\(/", 'proxyProcessJavascriptCB5', $script);
  592.  
  593.     // x = document; replacement (unused)
  594.      $script=preg_replace_callback("/[=]\s*document(\s*[^\.\s])/", "proxyProtectJavascriptCB6", $script);
  595.  
  596.     return $script;
  597. }
  598.  
  599.  
  600. /**
  601.  * @desc url() replacement preg_match_callback functions
  602.  */
  603. function proxyProcessCSSMatch($matches) {return $matches[1].processHRef($matches[2]).$matches[3];}
  604. function proxyProcessCSSMatch2($matches){
  605.     $url=trim($matches[2]);
  606.     $sep="'";
  607.     if($url[0]=='"' || $url[0]=="'") {
  608.         $sep=$url[0];
  609.         $url=substr($url,1,strlen($url)-2);
  610.     }
  611.     return $matches[1].$sep.processHRef($url).$sep.$matches[3];
  612. }
  613.  
  614. /**
  615.  * @desc process CSS style section
  616.  *
  617.  * @param string $style : CSS text
  618.  * @return string processed CSS
  619.  */
  620. function proxyProcessCSS($style){
  621.     $style=preg_replace_callback("/(@import\s*['|\"])(.*?)(['|\"])/i", 'proxyProcessCSSMatch',$style);
  622.     return preg_replace_callback("/(url\s*[(])(.*?)([)])/i", 'proxyProcessCSSMatch2',$style);
  623. }
  624.  
  625. /**
  626.  * Process HTML document, echo result
  627.  *
  628.  * @param string $body : HTML code (whole doc, not only <body>)
  629.  */
  630. function proxyProcessHTML($body,$contentType=false){
  631.     cfChronoAddPoint('start');
  632.  
  633.     // Workaround : DOM parser bug on <script> tags including other tags (in document.write for example) => base64 encode content
  634.     //$body=preg_replace_callback("/(<\s*script\s*([^>]*)>)((.|\n|\r)+?)<\/script/i", "proxyProtectJavascriptCB", $body);
  635.     $pos=0;$pos3=0;
  636.     while(($pos=stripos($body,'<script',$pos))){
  637.         if(($pos3=strpos($body,'>',$pos+6)) && ($pos2=stripos($body,'</script',$pos3))){
  638.             $body=substr($body,0,$pos3+1).'b64'.base64_encode(substr($body,$pos3+1,$pos2-$pos3-1)).substr($body,$pos2);
  639.             $pos=$pos2;
  640.         }
  641.         else break;
  642.     }
  643.  
  644.  
  645.     /**
  646.      * Try to find encoding before loading HTML in dom document
  647.      * (workaround for ill-detected encoding if <title> is before <meta HTTP-EQUIV="content-type" ...>
  648.      */
  649.  
  650.     // Used to state wether a <title> has been found before <meta> defining encoding (meaning that things will have to be fixed
  651.     // if encoding passed into headers, consider that it has to be fixed
  652.     $titleBeforeMeta=true;
  653.  
  654.     // If no charset passed into headers, try to find it into meta data
  655.     if(!$contentType || stripos($contentType,'charset')===false){
  656.         $dom = new DOMDocument();
  657.         @$dom->loadHTML($body);
  658.         if($dom->getElementsByTagName('head')->length){
  659.             $titleBeforeMeta=false;
  660.             $child=$dom->getElementsByTagName('head')->item(0)->firstChild;
  661.             while ($child) {
  662.                 // <title> found
  663.                 if($child->nodeName=='title') $titleBeforeMeta=true;
  664.  
  665.                 elseif($child->nodeName=='meta' && $child->hasAttribute("http-equiv") && $child->hasAttribute("content")
  666.                     && $child->getAttribute("http-equiv")=='content-type') {
  667.                     // Charset found !
  668.                     if(stripos($child->getAttribute("content"),'charset')!==false){
  669.                         $contentType=$child->getAttribute("content");
  670.                         break;
  671.                     }
  672.                 }
  673.                 $child=$child->nextSibling;
  674.             }
  675.         }
  676.     }
  677.  
  678.  
  679.     // If a charset has been passed into headers or has been found in <meta>
  680.     // If !$titleBeforeMeta, no need to re-parse document
  681.     if($titleBeforeMeta && $contentType && stripos($contentType,'charset')!==false){
  682.         // If document has a <head>, append content-type meta right at the begining
  683.         if(($pos=stripos($body,'<head'))!==false){
  684.             while ($body[$pos]!='>' && $pos<99999) $pos++;
  685.             $body=substr($body,0,$pos+1).'<meta HTTP-EQUIV="content-type" CONTENT="'.$contentType.'">'.substr($body,$pos+1);
  686.         }
  687.         else $body='<meta HTTP-EQUIV="content-type" CONTENT="'.$contentType.'">'.$body;
  688.  
  689.         // Load DOM
  690.         $dom = new DOMDocument();
  691.         @$dom->loadHTML($body);
  692.     }
  693.  
  694.  
  695.     //cfDbg($dom->getElementsByTagName('head')->length,1);
  696.     // Recursively process href, src, on... attributes
  697.  
  698.  
  699.     // Check for <base> node
  700.     $_ENV['baseHref']=false;
  701.     foreach($dom->getElementsByTagName('base') as $v){
  702.         if($v->hasAttribute('href')) {
  703.             $_ENV['baseHref']=$v->getAttribute('href');
  704.             // Set trailing slash
  705.             if(substr($_ENV['baseHref'],-1)!='/') $_ENV['baseHref'].='/';
  706.             // Make baseHref absolute
  707.             if(substr(strtolower($_ENV['baseHref']),0,4)!='http'){
  708.                 while(substr($_ENV['baseHref'],0,1)=='/') $_ENV['baseHref']=substr($_ENV['baseHref'],1);
  709.                 $_ENV['baseHref']=$_ENV['siteURLHost'].$_ENV['baseHref'];
  710.             }
  711.             // Remove href attribute so base is not utilised anymore (shouldn't happend anyway as URLs are all set absolutes)
  712.             $v->removeAttribute('href');
  713.             break;
  714.         }
  715.     }
  716.  
  717.     // Process href, src, onclick, onmouse... nodes attributes
  718.     foreach ($dom->childNodes as $cn) if($cn->nodeType==XML_ELEMENT_NODE) proxyProcessNode($cn);
  719.  
  720.     // Process meta http-equiv / content = refresh
  721.     foreach ($dom->getElementsByTagName('meta') as $v) if($v->hasAttribute('http-equiv') && $v->hasAttribute('content') && strtolower($v->getAttribute('http-equiv'))=='refresh') {
  722.         if(strpos($v->getAttribute('content'),';'))    {
  723.             $refreshURL=trim(substr($v->getAttribute('content'),strpos($v->getAttribute('content'),';')+1));
  724.             if(!$refreshURL) continue;
  725.             if(substr($refreshURL,0,4)=='URL=') $refreshURL=substr($refreshURL,4);
  726.             $v->setAttribute('content',substr($v->getAttribute('content'),0,strpos($v->getAttribute('content'),';')+1).'URL='.proxyEncodeUrlPHP($refreshURL));
  727.         }
  728.     }
  729.  
  730.     // Process javascript nodes (assume all scripts are javascript...)
  731.     foreach ($dom->getElementsByTagName('script') as $v) {
  732.  
  733.         if($v->nodeValue) {
  734.             if(substr($v->nodeValue,0,3)=='b64')
  735.                 $v->nodeValue='b64'.base64_encode(proxyProcessJavascript(base64_decode(substr($v->nodeValue,3))));
  736.             else
  737.                 $v->nodeValue='b64'.base64_encode(proxyProcessJavascript($v->nodeValue));
  738.         }
  739.     }
  740.     // Process CSS style nodes (assume all style are CSS...)
  741.     foreach ($dom->getElementsByTagName('style') as $v) {
  742.         $nv=proxyProcessCSS($v->nodeValue);
  743.         // Process comment nodes
  744.         foreach ($v->childNodes as $cssN) if($cssN->nodeType==XML_COMMENT_NODE) $nv.="\n".proxyProcessCSS($cssN->nodeValue);
  745.         $v->nodeValue=$nv;
  746.     }
  747.  
  748.     /**
  749.      * Insert proxy javascript
  750.      */
  751.     $script=$dom->createElement('script');
  752.     $script->setAttribute("type","text/javascript");
  753.     $scriptContent =";var baseURLProxy=\"".$_ENV['baseURLProxy']."\";\n";
  754.     $scriptContent.="var proxyBaseHref=\"".$_ENV['baseHref']."\";\n";
  755.     $scriptContent.="var siteHref=new proxyDocumentLocation(\"".$_ENV['baseURL']."\");\n";
  756.     $scriptContent.="var proxyDoc=new proxyDocument();\n";
  757.  
  758.     // Send cookies in a javascript var so they can be manipulated in javascript:
  759.     // Browse all proxy-stored cookies and determine which ones should be sent to page
  760.     $cookies='';
  761.     if(isset($_ENV['browserCookies'])) foreach ($_ENV['browserCookies'] as $k=>$v){
  762.         // If correct domain and path
  763.         if(substr($_ENV['siteDecodedURL']['host'],-strlen($v['domain']))==$v['domain'] && substr(((isset($_ENV['siteDecodedURL']['path']))?$_ENV['siteDecodedURL']['path']:'/'),0,strlen($v['path']))==$v['path']){
  764.             // Add cookie to headers (if not secure or https)
  765.             if(!$v['secure'] || (isset($_ENV['siteDecodedURL']['protocol']) && $_ENV['siteDecodedURL']['protocol']=='https')) $cookies.='; '.$v['name'].'='.$v['value'];
  766.         }
  767.     }
  768.     $scriptContent.='var proxyCookies="'.str_replace('"','\\"',substr($cookies,2))."\";\n";
  769.     $scriptContent.="\n\n\n\n\n/* ------------------------------------------------------------------ */\n\n\n\n\n\n";
  770.  
  771.  
  772.     $script->nodeValue=file_get_contents(cfAppDocRoot().'/js/proxyScripts.js').$scriptContent;
  773.  
  774.     // Insert into head if a head is found
  775.     if($dom->getElementsByTagName('head')->length){
  776.         // Insert before first script
  777.         if($dom->getElementsByTagName('head')->item(0)->getElementsByTagName('script')->length>0){
  778.             $dom->getElementsByTagName('head')->item(0)->insertBefore($script,
  779.                 $dom->getElementsByTagName('head')->item(0)->getElementsByTagName('script')->item(0));
  780.         }
  781.         // If no script, insert at head's end
  782.         else
  783.             $dom->getElementsByTagName('head')->item(0)->appendChild($script);
  784.     }
  785.     // Insert proxy nodes
  786.     if($dom->getElementsByTagName('body')->length){
  787.         $newNode=$dom->createElement('div');
  788.         $newNode->setAttribute("style","display:none");
  789.         $newNode->setAttribute("id","proxyDWDOM");
  790.         $dom->getElementsByTagName('body')->item(0)->insertBefore($newNode,$dom->getElementsByTagName('body')->item(0)->firstChild);
  791.  
  792.         $newNode=$dom->createElement('script');
  793.         $newNode->setAttribute("type","text/javascript");
  794.         $newNode->nodeValue='var proxyDocumentLocationNode=document.getElementById("proxyDocumentLocationNode");';
  795.         $dom->getElementsByTagName('body')->item(0)->insertBefore($newNode,$dom->getElementsByTagName('body')->item(0)->firstChild);
  796.  
  797.         $newNode=$dom->createElement('input');
  798.         $newNode->setAttribute("style","display:none");
  799.         $newNode->setAttribute("id","proxyDocumentLocationNode");
  800.         $dom->getElementsByTagName('body')->item(0)->insertBefore($newNode,$dom->getElementsByTagName('body')->item(0)->firstChild);
  801.  
  802.     }
  803.     // Workaround : DOM parser bug on <script> tags including other tags (in document.write for example) => base64 decode content
  804.     $encoded=preg_replace_callback("/>b64([a-zA-Z0-9\/+]*[=]{0,2})</", "proxyUnprotectJavascriptCB", @$dom->saveHTML());
  805.     return $encoded;
  806.  
  807.     //cfVarDump($_SERVER['REQUEST_URI'].' -> '.$_ENV['baseURL']);
  808.     //file_put_contents($debugDirectory.'/pageS.html',$body);
  809.     //file_put_contents($debugDirectory.'/pageE.html',$encoded);
  810.  
  811.     cfChronoAddPoint('fin encodage');
  812.     return;
  813.     require_once(INCLUDE_DIR.'Text/Highlighter.php');
  814. ?>
  815. <style type="text/css">
  816.     .hl-main {font-family: monospace; font-size:13px;background:white}
  817.     .hl-gutter { background-color: #CCCCCC; padding-right: 10px;
  818.              font-family: monospace; font-size:13px;}
  819.     .hl-table {border: solid 1px #000000; }
  820.  
  821.     .hl-default { color: #000000;}
  822.     .hl-code { color: #7f7f33; }
  823.     .hl-brackets { color: #009966; }
  824.     .hl-comment { color: white; background:#AAF}
  825.     .hl-quotes { color: #00007F; }
  826.     .hl-string { color: #009900; }
  827.     .hl-identifier { color: #000000; }
  828.     .hl-reserved { color: #0000FF; }
  829.     .hl-inlinedoc { color: #EEF; background:#AAF}
  830.     .hl-var { color: #CC3300; }
  831.     .hl-url { color: #FF0000; text-decoration:underline}
  832.     .hl-special { color: #0000FF; }
  833.     .hl-number { color: #007F00; }
  834.     .hl-inlinetags { color: #FF0000; }
  835. </style>
  836. <div id="proxyBrowser">
  837.     <div id="proxyBrowserSource" style="width:100%; border:1px solid #DDD">
  838.         <div style="background:#DFD" onclick="if(document.getElementById('proxyBrowserSourceDiv').style.display=='inline') document.getElementById('proxyBrowserSourceDiv').style.display='none'; else document.getElementById('proxyBrowserSourceDiv').style.display='inline'">
  839.             <span style="font-weight:bold;font-size:18px"> + SOURCE </span>
  840.         </div>
  841.         <div id="proxyBrowserSourceDiv" style="display:none">
  842. <?php
  843.     $hl =& Text_Highlighter::factory('HTML');
  844.     //echo $hl->highlight($body);;
  845.     //echo str_replace('<','<',$body);
  846. ?>
  847.         </div>
  848.     </div>
  849.  
  850.     <div id="proxyBrowserEncoded" style="width:100%; border:1px solid #DDD;margin-top:3px">
  851.         <div style="background:#FDD" onclick="if(document.getElementById('proxyBrowserEncodedDiv').style.display=='inline') document.getElementById('proxyBrowserEncodedDiv').style.display='none'; else document.getElementById('proxyBrowserEncodedDiv').style.display='inline'">
  852.             <span style="font-weight:bold;font-size:18px"> + ENCODED </span>
  853.         </div>
  854.         <div id="proxyBrowserEncodedDiv" style="display:none">
  855. <?php
  856.     $hl =& Text_Highlighter::factory('HTML');
  857.     echo $hl->highlight($encoded);
  858.     //echo str_replace('<','<',$encoded);
  859. //echo str_replace('<','<br><',$dom->saveHTML());
  860. ?>
  861.         </div>
  862.     </div>
  863. </div>
  864. <?php
  865. }
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878. /** **********************************************************************************************************************************************************
  879.  *
  880.  * @desc load and process given URL
  881.  *
  882.  * @param string $url
  883.  *
  884.  ********************************************************************************************************************************************************** */
  885.  
  886. function proxyProcessPage($decodedURL){
  887.     if(!$decodedURL) return ;
  888.  
  889.  
  890.     // Set proxy settings (if not already set)
  891.     proxySetOptions();
  892.  
  893.     //cfDbg(array('URL'=>$decodedURL)+getallheaders());
  894.  
  895.     /**
  896.      * Get server-side stored cookies
  897.      */
  898.     if(!$_ENV['options']['noCookies']){
  899.         $cookiesUpdated=false;
  900.         // Get session cookies
  901.         $_ENV['browserCookies']=cfRGetVar('sessionCookies');
  902.  
  903.         if(!$_ENV['browserCookies']) $_ENV['browserCookies']=array();
  904.         // Add persistent cookies
  905.         if(file_exists(cfAppResourceDir().'/persistentCookies.txt')) foreach (unserialize(file_get_contents(cfAppResourceDir().'/persistentCookies.txt')) as $v) $_ENV['browserCookies'][]=$v;
  906.  
  907.         // Clear expired cookies
  908.         foreach ($_ENV['browserCookies'] as $k=>$v) if($v['expires']!=='session' && $v['expires']<time()) {
  909.             unset($_ENV['browserCookies'][$k]);
  910.             $cookiesUpdated=true;
  911.         }
  912.     }
  913.  
  914. /*
  915.  ***************************************************************************************************************************
  916.  * WEB BROWSER => PROXY
  917.  ***************************************************************************************************************************
  918.  */
  919.  
  920.     //if(substr($decodedURL,0,8)=='https://') cfDbg($decodedURL,1);
  921.     if(strtolower(substr($decodedURL,0,7))!='http://' && strtolower(substr($decodedURL,0,8))!='https://') $decodedURL='http://'.$decodedURL;
  922.  
  923.     // Parse and store base URL
  924.     $_ENV['baseURL']=$decodedURL;
  925.     if(!$url=@parse_url($decodedURL)) exit;
  926.     $_ENV['siteDecodedURL']=$url;
  927.  
  928.     // Protect LAN and localhost if required by config
  929.     if(cfIsOnLAN($url['host']) && !cfRGetVar('allowLocalRequests')) {
  930.         require_once(INCLUDE_DIR.'outputFunctions.php');
  931.         outDisplayErrorPage(cfCaption('genNoAccess'));
  932.     }
  933.  
  934.     $_ENV['siteURLScheme']= ((isset($url['scheme']))?$url['scheme']:((isset($url['port']) && $url['port']==443)?'https':'http'));
  935.     $_ENV['siteURLHost']=$_ENV['siteURLScheme'].'://';
  936.     if(isset($url['user']) && isset($url['pass'])) $_ENV['siteURLHost'].=$url['user'].':'.$url['pass'].'@';
  937.     $_ENV['siteURLHost'].=$url['host'].(isset($url['port'])?':'.$url['port']:'');
  938.  
  939.     if(isset($url['path']) && $url['path']!='/'){
  940.         if(substr($url['path'],-1)=='/') $_ENV['siteURLPath']=substr($url['path'],0,strlen($url['path'])-1);
  941.         else $_ENV['siteURLPath']=dirname($url['path']);
  942.         if($_ENV['siteURLPath']=='\\') $_ENV['siteURLPath']='';
  943.     }
  944.     else $_ENV['siteURLPath']='';
  945.     $_ENV['baseURLGet']=((isset($url['query'])?'?'.$url['query']:''));
  946.  
  947.  
  948.     // Proxy base URL
  949.     if(cfGGetVar('hostName'))
  950.         $_ENV['baseURLProxy']=cfGGetVar('hostName');
  951.     else{
  952.         $_ENV['baseURLProxy']=((isset($_SERVER['HTTPS']))?'https':'http').'://'.$_SERVER['SERVER_ADDR'].':'.$_SERVER['SERVER_PORT'];
  953.     }
  954.     $_ENV['baseURLProxy']=str_replace('127.0.0.1','localhost',$_ENV['baseURLProxy']).dirname($_SERVER['PHP_SELF']).'/';
  955.  
  956.  
  957.     // Process cookies received from browser to detect modifications (new/deleted/updated)
  958.     if(!$_ENV['options']['noCookies'] && isset($_COOKIE)){
  959.         foreach ($_COOKIE as $cookieName=>$cookieValue){
  960.             // If this cookie is used by proxy
  961.             if(substr($cookieName,0,11)=='proxyCookie') {
  962.                 $cookiesUpdated=true;
  963.                 // Get cookie name
  964.                 $cookieName=substr($cookieName,11);
  965.                 // Get cookie expiry date and value
  966.                 list($void,$expires,$cookieValue)=explode('/',$cookieValue,3);
  967.  
  968.                 // See if this cookie already exists
  969.                 foreach ($_ENV['browserCookies'] as $k=>$v){
  970.                     // If cookie has same name and host and path match, remove
  971.                     if($v['name']==$cookieName && substr($url['host'],-strlen($v['domain']))==$v['domain'] && substr(((isset($url['path']))?$url['path']:'/'),0,strlen($v['path']))==$v['path']) unset($_ENV['browserCookies'][$k]);
  972.                 }
  973.                 // Add it to list
  974.                 $_ENV['browserCookies'][]=array('name'=>$cookieName,'value'=>$cookieValue,'domain'=>$url['host'],'path'=>'/','expires'=>$expires,'secure'=>false);
  975.             }
  976.         }
  977.     }
  978.  
  979.  
  980. /*
  981.  ***************************************************************************************************************************
  982.  * PROXY => SITE
  983.  ***************************************************************************************************************************
  984.  */
  985. //cfDbg(array('URL:'=>$decodedURL,' '=>' ')+getallheaders(),1);
  986.  
  987.     // Set browser headers
  988.     foreach (getallheaders() as $key=>$value) $inHeaders[strtolower($key)]=$value;
  989.     unset($inHeaders['host']);
  990.     unset($inHeaders['content-length']);
  991.  
  992.     // Remove cookies sent by browser
  993.     unset($inHeaders['cookie']);
  994.     unset($inHeaders['cookie2']);
  995.  
  996.     // Set cookies
  997.     if(!$_ENV['options']['noCookies']) {
  998.         $inHeaders['cookie']='';
  999.  
  1000.         foreach ($_ENV['browserCookies'] as $k=>$v){
  1001.             // If matching domain and path
  1002.             if(substr($url['host'],-strlen($v['domain']))==$v['domain'] && substr(((isset($url['path']))?$url['path']:'/'),0,strlen($v['path']))==$v['path']){
  1003.                 // Add cookie to headers (if not secure or https)
  1004.                 if(!$v['secure'] || (isset($_ENV['siteDecodedURL']['protocol']) && $url['protocol']=='https')) $inHeaders['cookie'].='; '.$v['name'].'='.$v['value'];
  1005.             }
  1006.         }
  1007.         // Remove 1st ";"
  1008.         if($inHeaders['cookie']) $inHeaders['cookie']=substr($inHeaders['cookie'],1); else unset($inHeaders['cookie']);
  1009.     }
  1010.     //if(isset($inHeaders['cookie'])) cfDbg('Cookies envoyΘs au serveur ('.$_ENV['siteURLPath'].'): '.$inHeaders['cookie']);
  1011.  
  1012.     //unset($inHeaders['accept-encoding']);
  1013.     unset($inHeaders['te']);
  1014.  
  1015.     //unset($inHeaders['Content-Type']);
  1016.     //unset($inHeaders['accept']);
  1017.     //unset($inHeaders['accept-charset']);
  1018.  
  1019.     // Process Referer
  1020.     if($_ENV['options']['noReferer']) unset($inHeaders['referer']);
  1021.     elseif(isset($inHeaders['referer'])) $inHeaders['referer']=proxyDecodeUrlPHP($inHeaders['referer']);
  1022.  
  1023.     // Debug only
  1024.     unset($inHeaders['if-modified-since']);
  1025.     unset($inHeaders['if-none-match']);
  1026.  
  1027.     // Close connections between proxy and site
  1028.     $inHeaders['connection']='Close';
  1029.  
  1030.     // Identifie as weezo proxy to avoid bypassing weezo IP checks
  1031.     if(!isset($inHeaders['user-agent'])) $inHeaders['user-agent']='weezoProxy'; else $inHeaders['user-agent'].=' /weezoProxy';
  1032.  
  1033.     // Process POST request
  1034.     $POSTDATA='';
  1035.     if(isset($GLOBALS['HTTP_RAW_POST_DATA']))
  1036.         // Unknown encoding
  1037.         $POSTDATA=$GLOBALS['HTTP_RAW_POST_DATA'];
  1038.     elseif (isset($_POST) && count($_POST)){
  1039.         // multipart/form-data
  1040.         if(isset($inHeaders['content-type']) && stripos($inHeaders['content-type'],'multipart/form-data')!==false){
  1041.             if(stripos($inHeaders['content-type'],'boundary=')!==false){
  1042.                 $boundary=substr($inHeaders['content-type'],stripos($inHeaders['content-type'],'boundary=')+9);
  1043.             }
  1044.             else {
  1045.                 $boundary='----------ek8VX07YznAePPdwJSbq9d';
  1046.                 $inHeaders['content-type']='multipart/form-data; '.$boundary;
  1047.             }
  1048.             foreach ($_POST as $key=>$value){
  1049.                 $POSTDATA.='--'.$boundary."\r\nContent-Disposition: form-data; name=\"".$key."\"\r\n\r\n".$value."\r\n";
  1050.             }
  1051.             $POSTDATA.='--'.$boundary.'--';
  1052.         }
  1053.         // Assume application/x-www-form-urlencoded
  1054.         else{
  1055.             foreach ($_POST as $key=>$value) $POSTDATA.='&'.urlencode($key).'='.urlencode($value);
  1056.             $POSTDATA=substr($POSTDATA,1);
  1057.         }
  1058.     }
  1059.     elseif (isset($inHeaders['content-type'])) unset($inHeaders['content-type']);
  1060.     if($POSTDATA) $inHeaders['content-length']=strlen($POSTDATA);
  1061. cfChronoAddPoint('start Loading page');
  1062.  
  1063.     foreach ($inHeaders as $k=>$v){$ucHeaders[str_replace(' ','-',ucfirst(str_replace('-',' ',$k)))]=$v;}
  1064.     $inHeaders=$ucHeaders;
  1065.  
  1066.  
  1067.     //cfDbg($inHeaders,1);
  1068.  
  1069.     // Open handle on document
  1070.     if(!($handle=cfSocketHTTPRequest($decodedURL,4,false,$err,$void,false,true,$inHeaders,$POSTDATA))) {
  1071.         //cfDbg('No socket connection to '.$decodedURL,1);
  1072.         return null;
  1073.     }
  1074.  
  1075.  
  1076. /*
  1077.  ***************************************************************************************************************************
  1078.  * SITE => PROXY
  1079.  ***************************************************************************************************************************
  1080.  */
  1081.  
  1082.     // Read Headers
  1083.     $data=''; $body='';
  1084.     while(!feof($handle) && (!strpos($data,"\r\n\r\n")) && (!strpos($data,"\n\r\n\r"))) $data .= @fread($handle, 5120);
  1085. cfChronoAddPoint('done Loading header');
  1086.  
  1087.     // Parse Header
  1088.     $fullStatus='';cfParseHTTPResponse($data,$status,$body,$headers,$fullStatus);
  1089.  
  1090. //cfDbg('RETURNED HEADERS');
  1091. //cfDbg($fullStatus);
  1092. //cfDbg($headers);
  1093.  
  1094.     // Flatten headers (other than set-cookie)
  1095.     foreach ($headers as $k=>$v) if(is_array($v) && $k!='set-cookie') $headers[$k]=$v[count($v)-1];
  1096.  
  1097.     // Get document's mime type
  1098.     if(strpos($decodedURL,'?')) $path=substr($decodedURL,0,strpos($decodedURL,'?')); else $path=$decodedURL;
  1099.     if(isset($headers['mime-type'])) $mimeType=$headers['mime-type'];
  1100.     elseif (isset($headers['content-type'])) $mimeType=((strpos($headers['content-type'],';')?substr($headers['content-type'],0,strpos($headers['content-type'],';')):$headers['content-type']));
  1101.     else{
  1102.         require_once(INCLUDE_DIR.'mime_type.php');
  1103.         $mimeType=mimeType($path);
  1104.     }
  1105.     if(!$mimeType) $mimeType=='text/html'; // If mime type not found, treat as HTML
  1106.  
  1107.     // Correct js mime type
  1108.     if(cfFileExtension($path)=='js' || strpos($_SERVER['REQUEST_URI'],'/eourl/js')) {
  1109.         if(isset($headers['content-type'])) $headers['content-type']=str_ireplace($mimeType,'text/javascript',$headers['content-type']);
  1110.         $mimeType='text/javascript';
  1111.     }
  1112.     // Correct css mime type
  1113.     if(strpos($_SERVER['REQUEST_URI'],'/eourl/css')) $mimeType='text/css';
  1114.  
  1115.     // Process server-sent cookies
  1116.     if(isset($headers['set-cookie']) && !$_ENV['options']['noCookies']){
  1117.         if(!is_array($headers['set-cookie'])) $headers['set-cookie']=array(0=>$headers['set-cookie']);
  1118. //if(count($headers['set-cookie'])>5) cfDbg('SET '.count($headers['set-cookie']).' cookies !!!',1);
  1119.         foreach ($headers['set-cookie'] as $setCookieHeader){
  1120.             //cfDbg('set-cookie header: '.$setCookieHeader);
  1121.             $setCookie=explode(';',$setCookieHeader);
  1122.             @list($cookieName,$cookieValue)=explode('=',reset($setCookie),2);
  1123.             // If a cookie is sent
  1124.             if($cookieName && $cookieValue){
  1125.                 if(!$_ENV['options']['noCookies'] && isset($_COOKIE)){
  1126.                     // Set default cookie parameters
  1127.                     $cookieDomain=array_reverse(explode('.',$url['host']));
  1128.                     if(is_numeric($cookieDomain[0])) $cookieDomain=$url['host'];
  1129.                     elseif ($cookieDomain[0]=='localhost') $cookieDomain='127.0.0.1';
  1130.                     elseif(count($cookieDomain)==1) $cookieDomain=$cookieDomain[0];
  1131.                     else $cookieDomain='.'.$cookieDomain[1].'.'.$cookieDomain[0];
  1132.                     $cookiePath='/';
  1133.                     $cookieExpires='session';
  1134.                     $cookieSecure=false;
  1135.                     // Get set-cookie parameters
  1136.                     foreach ($setCookie as $v){
  1137.                         @list($key,$value)=explode('=',$v,2);
  1138.                         $key=trim($key);$value=trim($value);
  1139.                         if($key=='expires' && $value!='session') $cookieExpires=@strtotime($value);
  1140.                         elseif($key=='domain') $cookieDomain=$value;
  1141.                         elseif($key=='path') $cookiePath=$value;
  1142.                         elseif($key=='secure') $cookieSecure=true;
  1143.                     }
  1144.  
  1145.                     // Remove this cookie from proxy cookies list (if present)
  1146.                     foreach ($_ENV['browserCookies'] as $k=>$v)
  1147.                         if($v['name']==$cookieName && $v['domain']==$cookieDomain && $v['path']==$cookiePath) unset($_ENV['browserCookies'][$k]);
  1148.                     // Integrate this new cookie in proxy cookies list
  1149.                     $_ENV['browserCookies'][]=array('name'=>$cookieName,'value'=>$cookieValue,'domain'=>$cookieDomain,'path'=>$cookiePath,'secure'=>$cookieSecure,'expires'=>$cookieExpires);
  1150.                     $cookiesUpdated=true;
  1151.                 }
  1152.             }
  1153.         }
  1154.     }
  1155.  
  1156.     // Save proxy-stored cookies
  1157.     if(!$_ENV['options']['noCookies'] && $cookiesUpdated) {
  1158.         // Separate session cookies and persistent cookies
  1159.         $sessionCookies=array();
  1160.         $persistentCookies=array();
  1161.         foreach ($_ENV['browserCookies'] as $cookie){
  1162.             if($cookie['expires']=='session') $sessionCookies[]=$cookie; else $persistentCookies[]=$cookie;
  1163.         }
  1164.         // Save session cookies in a session var
  1165.         if(count($sessionCookies)){
  1166.             wSession_start();
  1167.             cfRSetVar('sessionCookies',$sessionCookies);
  1168.             wSession_write_close();
  1169.         }
  1170.         // Save persistent cookies in a file
  1171.         if(count($persistentCookies)) file_put_contents(cfAppResourceDir().'/persistentCookies.txt',serialize($persistentCookies));
  1172.     }
  1173.  
  1174. /*
  1175.  ***************************************************************************************************************************
  1176.  * PROXY => WEB BROWSER
  1177.  ***************************************************************************************************************************
  1178.  */
  1179.  
  1180.     // Debug
  1181.     $debugDirectory=cfRGetVar('debugDirectory');
  1182.     $debugExt=cfRGetVar('debugExt');
  1183.     $pathToFile=strtr($path,'<>?/\\:*"|','---------');
  1184.  
  1185.     // Don't send content-length now
  1186.     if(isset($headers['content-length'])){
  1187.         $contentLength=$headers['content-length'];
  1188.         unset($headers['content-length']);
  1189.     }
  1190.     else $contentLength=false;
  1191.  
  1192.     // Process body
  1193.     switch ($mimeType) {
  1194.         // HTML
  1195.         case 'text/plain':
  1196.         case 'text/php':
  1197.         case 'text/asp':
  1198.         case 'text/aspx':
  1199.         case 'text/html':
  1200.         case 'text/htm':
  1201.         case 'text/xml':
  1202.             // Read
  1203.             stream_set_blocking($handle,1);    while(!feof($handle)) $body.=@fread($handle, 8192); fclose($handle);
  1204.             // gzip decode
  1205.             if (isset($headers['content-encoding'])&& ($headers['content-encoding']=='gzip' || $headers['content-encoding']=='x-gzip')) $body=gzdecode($body);
  1206.             // unset unneeded headers an send headers
  1207.             unset($headers['content-length']);
  1208.             unset($headers['content-encoding']);
  1209.             proxySendHeadersToBrowser($fullStatus, $headers,false);
  1210.  
  1211.             // Clean BOM and reencode page
  1212.             $h[0]=ord(substr($body,0,1));
  1213.             $h[1]=ord(substr($body,1,1));
  1214.             $h[2]=ord(substr($body,2,1));
  1215.             $h[3]=ord(substr($body,3,1));
  1216.             if($h[0]==239 && $h[1]==187 && $h[2]==191) $body=mb_convert_encoding(substr($body,3), 'HTML-ENTITIES', "UTF-8");
  1217.             elseif ($h[0]==0 && $h[1]==0 && $h[2]==255 && $h[3]==254) $body=mb_convert_encoding(substr($body,4), 'HTML-ENTITIES', "UTF-32BE");
  1218.             elseif ($h[0]==255 && $h[1]==254 && $h[2]==0 && $h[3]==0) $body=mb_convert_encoding(substr($body,4), 'HTML-ENTITIES', "UTF-32LE");
  1219.             elseif ($h[0]==255 && $h[1]==254) $body=mb_convert_encoding(substr($body,2), 'HTML-ENTITIES', "UTF-16LE");
  1220.             elseif ($h[0]==254 && $h[1]==255) $body=mb_convert_encoding(substr($body,2), 'HTML-ENTITIES', "UTF-16BE");
  1221.             elseif ($h[0]==43 && $h[1]==47 && $h[1]==118) $body=mb_convert_encoding(substr($body,4), 'HTML-ENTITIES', "UTF-7");
  1222.  
  1223.             // Debug - source
  1224.             //$debugExt='html';
  1225.             //$debugDirectory='c:/P1/temp/proxy';
  1226.             if($debugDirectory && (strpos($debugExt,'html') || strpos($debugExt,'*'))) {@unlink($debugDirectory.'/html-'.$pathToFile.'-src.html'); cfAppendTextToFile($body,$debugDirectory.'/html-'.basename($path).'-src.html',false);}
  1227.  
  1228.             // Send processed HTML code
  1229.             if($mimeType!='text/xml') $body=proxyProcessHTML($body,isset($headers['content-type'])?$headers['content-type']:false);
  1230.             echo $body;
  1231.  
  1232.  
  1233.             // Debug - encoded
  1234.             if($debugDirectory && (strpos($debugExt,'html') || strpos($debugExt,'*'))) {@unlink($debugDirectory.'/html-'.$pathToFile.'-dest.html'); cfAppendTextToFile($body,$debugDirectory.'/html-'.basename($path).'-dest.html',false);}
  1235.             break;
  1236.  
  1237.  
  1238.  
  1239.  
  1240.         // Javascript
  1241.         case 'text/javascript':
  1242.         case 'application/x-javascript':
  1243.             // Read
  1244.             stream_set_blocking($handle,1);    while(!feof($handle)) $body.=@fread($handle, 8192); fclose($handle);
  1245.             // gzip decode
  1246.             if (isset($headers['content-encoding'])&& ($headers['content-encoding']=='gzip' || $headers['content-encoding']=='x-gzip')) $body=gzdecode($body);
  1247.             // unset unneeded headers an send headers
  1248.             unset($headers['content-length']);
  1249.             unset($headers['content-encoding']);
  1250.             proxySendHeadersToBrowser($fullStatus, $headers);
  1251.  
  1252.             // Debug - log source
  1253.             if($debugDirectory && (strpos($debugExt,'js') || strpos($debugExt,'*'))) {@unlink($debugDirectory.'/js-'.$pathToFile.'-src.js'); cfAppendTextToFile($body,$debugDirectory.'/js-'.basename($path).'-src.js',false);}
  1254.  
  1255.             // Send processed javascript code
  1256.             $out= proxyProcessJavascript($body);
  1257.             echo $out;
  1258.  
  1259.             // Debug - log destination
  1260.             if($debugDirectory && (strpos($debugExt,'js') || strpos($debugExt,'*'))) {@unlink($debugDirectory.'/js-'.$pathToFile.'-src.js'); cfAppendTextToFile($body,$debugDirectory.'/js-'.basename($path).'-src.js',false);}
  1261.  
  1262.             break;
  1263.         // CSS
  1264.         case 'text/css':
  1265.             // Read
  1266.             stream_set_blocking($handle,1);    while(!feof($handle)) $body.=@fread($handle, 8192); fclose($handle);
  1267.             // gzip decode
  1268.             if (isset($headers['content-encoding'])&& ($headers['content-encoding']=='gzip' || $headers['content-encoding']=='x-gzip')) $body=gzdecode($body);
  1269.             // unset unneeded headers an send headers
  1270.             unset($headers['content-length']);
  1271.             unset($headers['content-encoding']);
  1272.             proxySendHeadersToBrowser($fullStatus, $headers);
  1273.  
  1274.             // Debug - log source
  1275.             if($debugDirectory && (strpos($debugExt,'css') || strpos($debugExt,'*'))) {@unlink($debugDirectory.'/css-'.$pathToFile.'-src.css'); cfAppendTextToFile($body,$debugDirectory.'/css-'.basename($path).'-src.css',false);}
  1276.             // Send processed CSS code
  1277.             echo proxyProcessCSS($body);
  1278.  
  1279.             // Debug - log destination
  1280.             if($debugDirectory && (strpos($debugExt,'css') || strpos($debugExt,'*'))) {@unlink($debugDirectory.'/css-'.$pathToFile.'-dest.css'); cfAppendTextToFile($body,$debugDirectory.'/css-dest-'.basename($path).'-dest.css',false);}
  1281.  
  1282.             break;
  1283.         // Other : stream to output
  1284.         default:
  1285.             // Debug - log streamed data
  1286.             $fh=null;
  1287.             if($debugDirectory && (strpos($debugExt,'*') || strpos($debugExt,cfFileExtension($path)))){
  1288.                 @unlink($debugDirectory.'/untouched-'.$pathToFile);
  1289.                 $fh=fopen($debugDirectory.'/untouched-'.$pathToFile,'wb');
  1290.             }
  1291.  
  1292.             if (false && isset($headers['content-encoding'])&& ($headers['content-encoding']=='gzip' || $headers['content-encoding']=='x-gzip')) {
  1293.                 while(!feof($handle)) $body.=@fread($handle, 8192); fclose($handle);
  1294.                 $body=gzdecode($body);
  1295.                 if($sendHeaders) header('Content-Length: '.strlen($body));
  1296.                 echo $body;
  1297.                 // Debug
  1298.                 if($fh) fwrite($fh,$body);
  1299.             }
  1300.             else{
  1301.                 proxySendHeadersToBrowser($fullStatus, $headers);
  1302.                 echo $body;
  1303.                 // Debug
  1304.                 if($fh) {
  1305.                     fwrite($fh,$body);
  1306.                     while(!feof($handle)) {
  1307.                         $body=@fread($handle, 8192);
  1308.                         fwrite($fh,$body);
  1309.                         echo $body;
  1310.                     }
  1311.                 }
  1312.                 else while(!feof($handle)) echo @fread($handle, 8192);
  1313.  
  1314.                 fclose($handle);
  1315.             }
  1316.             // Close debug file
  1317.             if($fh) fclose($fh);
  1318.     }
  1319. }
  1320.  
  1321. ?>